/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022.
 * Description: A feature to allow logging of cpu stall into a separate kbox region
 * Author: wangbing <wangbing6@huawei.com>
 * Create: 2022-01-24
 */

#include <linux/rtos_sysctl.h>
#include "rtos_debug_cpustall.h"

static unsigned int cpustall_region_size;
int cpustall_region_id = -1;

#define MAX_UINT	(~0U)
#define MAX_LOG_SIZE	(MAX_UINT / 1024)
#define MIN_LOG_SIZE	4

static int region_vals[] = {MIN_LOG_SIZE, MAX_LOG_SIZE};
static DEFINE_MUTEX(cpustall_region_mutex);
static int proc_cpustall_region_size(struct ctl_table *table, int write,
			void __user *buffer, size_t *lenp, loff_t *ppos)
{
	int tmpid;
	int ret;
	unsigned int old_size;
	unsigned int region_size;

	mutex_lock(&cpustall_region_mutex);
	old_size = cpustall_region_size;
	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
	/*
	 * the region can be set only when the size is satisfied and it is writing
	 */
	if (ret == 0 && write) {
		region_size = cpustall_region_size * 1024;
		tmpid = kern_kbox_register_region("cpustall", region_size, NULL);
		if (tmpid < 0) {
			cpustall_region_size = old_size;
			pr_err("register cpustall region failed return %d!\n", tmpid);
			mutex_unlock(&cpustall_region_mutex);
			return tmpid;
		}
		cpustall_region_id = tmpid;
	}
	mutex_unlock(&cpustall_region_mutex);
	return ret;
}

static struct ctl_table rtos_cpu_sysctls[] = {
	{
		.procname       = "cpustall_region_size",
		.data           = &cpustall_region_size,
		.maxlen         = sizeof(unsigned int),
		.mode           = 0640,
		.proc_handler   = proc_cpustall_region_size,
		.extra1		= &region_vals[0],
		.extra2		= &region_vals[1],
	},
	{}
};

rtos_kernel_sysctls_proc_init(rtos_cpustall, rtos_cpu_sysctls);

